/**
 *
 */
package com.kingcore.director.main;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Locale;
import java.util.Properties;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import wzw.jdbc.ConnectionManager;
import wzw.security.MD5;
import wzw.util.ComponentUtil;
import wzw.util.FileUtils;

import com.ice.jni.registry.Registry;
import com.kingcore.director.DirectorConstants;
import com.kingcore.director.DirectorContext;
import com.kingcore.director.core.dao.DirectorCoreDao;
import com.kingcore.director.core.dao.impl.DirectorCoreDaoImpl;
import com.kingcore.director.core.util.DirectorComponentUtils;
import com.kingcore.director.core.util.DirectorFileUtils;
import com.kingcore.director.core.util.SearchEngineFactory;
import com.kingcore.framework.context.ApplicationContext;
import com.kingcore.framework.context.DataSourceManager;
import com.kingcore.framework.context.DatabaseManager;
import com.kingcore.framework.context.PlainDatabase;
import com.kingcore.framework.jdbc.ResultSetBeanExtractor;
import com.kingcore.framework.jdbc.SmartResultSetBeanExtractor;

/**
 * @author WZWEN
 *
 */
public class Main {

	//static { System.out.println("------------11111------"); };

	private static Main app;         //主入口对象
	private static MainFrame mainFrame;   //应用程序窗体对象
	public static String mainConfigFolder = "conf";   //配置文件根目录
	public static String mainConfigFile = File.separator+mainConfigFolder +File.separator+ "app.properties";   //起始配置文件
	public static int MainFrame_Size_Width = 1200;   //应用程序窗体对象宽  4:3
	public static int MainFrame_Size_Height = 900;   //应用程序窗体对象高
	private static int Encrypt_Time=8;   //授权加密次数
	public static String MainFrame_Shortcut_Key = "";   //打开应用程序快捷键
	public static String MiniWindow_Shortcut_Key = "";
	
	private static Logger log=Logger.getLogger(Main.class);
	public static String Default_DataSource_Name = "main";  //三个以上地方使用到就定义变量or常量
	public static String Crm_DataSource_Name = "crm";

	public static Boolean isNoDisturbOpen = false;
	
	private int init() {
		
		// 初始系统基本配置(非数据库的) include:log4j,net proxy,kingcore framework
		initSystemConfig();
		
		//初始log4j配置，前面使用log4j输出可能有问题，建议使用System.out输出。
		initLog4j();
		
		//网络访问代理设置
		if(DirectorConstants.Ad_Index_Url.indexOf("127.0.0.1")<0){ //非本地访问可能需要设置代理
			setAppProxy();
		}
		
		initKingCoreFramework();   // 初始Wpub Framework，包括dbpool,其他接口对象等
		
		//系统升级包，放在数据库配置初始之后、数据库操作之前。
		int ret = SystemUpdater.getInstance().updateDatabase(ApplicationContext.getInstance().getDataSourceManager(),
						DirectorConstants.System_App_Home );
//		if (ret>0) { //restart if update successfully
//			restart();
//			return -1;  //stop this one
//		}

		//启动主界面
		initAppEnviroment();   // 初始其他环境变量(包括数据库的)
		// 设置对HTTP进行代理,key可以写成http.proxyXxxx或proxyXxxx两种形式
        // System.setProperty("http.proxyType", "4");

		return 1;
 	}
	
	//设置应用程序网络访问代理
	public void setAppProxy() {
		String proxyStr = Registry.getProxy();
		if(proxyStr!=null && proxyStr.indexOf(":")>-1){
			int pos = proxyStr.indexOf(":");
			setHttpProxy( proxyStr.substring(0,pos), proxyStr.substring(pos+1) );
		}
	}

	public void setHttpProxy(String host, String port) {
        System.setProperty("http.proxySet", "true");
        System.setProperty("http.proxyHost", host); //"172.16.33.11");
        System.setProperty("http.proxyPort",  port); //"808" );
//		System.getProperties().put("socksProxySet", Boolean.valueOf(true));
//		System.getProperties().put("socksProxyHost", "172.16.33.11");//getSocksProxyHost() );
//		System.getProperties().put("socksProxyPort", "808");//getSocksProxyPort() );
	}
	
	private void initSystemConfig() {

		//系统目录，文件定位，采用绝对路径，不要放在classes目录下面。
		DirectorConstants.System_App_Home = System.getProperty("user.dir");
		DirectorConstants.System_App_ConfigPath = DirectorConstants.System_App_Home + File.separator + mainConfigFolder;
		System.out.println("System_App_Home="+DirectorConstants.System_App_Home
				  +"\n\tSystem_App_ConfigPath="+DirectorConstants.System_App_ConfigPath);

		//InputStream is = getClass().getResourceAsStream( FileUtils.convert2LinuxPath(mainConfigFile) );
		try {
			InputStream is = new FileInputStream( FileUtils.convert2LinuxPath( DirectorConstants.System_App_Home + mainConfigFile) );
			Properties mainProps = new Properties();
			mainProps.load(is);
			String runModel = mainProps.getProperty("run-model", "prod");
			//运行模式
			DirectorConstants.System_RunMode_Val = runModel;
			//广告地址及刷新间隔
			DirectorConstants.Ad_Index_Url = mainProps.getProperty("Ad_Index_Url", "http://127.0.0.1:8980/pda/ad/index.jsp?type=${type}");
			DirectorConstants.Ad_Fetch_Interval = Integer.parseInt( mainProps.getProperty("Ad_Fetch_Interval", "1") );

			//String configFileDirectory = getClass().get arg0.getServletContext().getRealPath("/WEB-INF/conf/" + bean.getInstanceType());
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	

	private void initLog4j( ) {
		String configFileDirectory = DirectorConstants.System_App_ConfigPath + File.separator 
				 + DirectorConstants.System_RunMode_Val;
		// initialize log4J
		System.out.println("runModel:"+DirectorConstants.System_RunMode_Val + ",configFileDirectory="+configFileDirectory);
		String log4jConf= FileUtils.convert2LinuxPath(configFileDirectory + File.separator +"log4j.properties");

		try {
			InputStream inputStream = new FileInputStream(log4jConf);
			Properties props = new Properties();
			props.load(inputStream);
			PropertyConfigurator.configure(props);	
			log.info("init Log4j configuration successfully!");
			
		} catch (IOException e) {
			log.error(e);
			e.printStackTrace();
		}	
	}

	/**
	 * 
	 * <p>Object初始，相当于ioc，但是没有使用ioc框架如spring，简化jar数量。</p>
	 * @author Zeven on Mar 20, 2009
	 */
	private void initKingCoreFramework() {
		//DataSourceManager之外的个性的设置要求。
		ConnectionManager.getInstance().setAppHome( DirectorConstants.System_App_Home );

		// 注入 ApplicationContext，而非DbBean，保持所有应用程序一致。 
		//可以采用setter编码，也可以xml配置使用ioc框架注入。
		ApplicationContext appContext = ApplicationContext.getInstance();
		DataSourceManager dataSourceManager = ConnectionManager.getInstance();
		ResultSetBeanExtractor resultSetBeanExtractor = new SmartResultSetBeanExtractor();//PlainResultSetBeanExtractor
		DatabaseManager databaseManager = new PlainDatabase(); 
		appContext.initContext( dataSourceManager, 
									DirectorConstants.System_App_ConfigPath, 
									Main.Default_DataSource_Name );
		appContext.setResultSetBeanExtractor(resultSetBeanExtractor);
		appContext.setDatabaseManager(databaseManager);
		//wzw.bean.DbBean.setDataSourceManager(ConnectionManager.getInstance());
	}

	/**
	 * 
	 * <p>给某些系统环境变量赋值。</p>
	 * @author Zeven on 2010-6-30
	 */
	private void initAppEnviroment() {
		System.out.println("当前支持时间单位为："+DirectorConstants.IntervalUints[0].length +"个." );
		for (int i = 0; i < DirectorConstants.IntervalUints[0].length; i++) {
			DirectorConstants.intervalUintsNameMap.put(
					DirectorConstants.IntervalUints[DirectorConstants.IntervalUints_Index_Code][i],
					DirectorConstants.IntervalUints[DirectorConstants.IntervalUints_Index_Name][i] );
			//System.out.println(Long.parseLong(DirectorConstants.intervalUints[2][i]));
			DirectorConstants.intervalUintsOffsetMap.put(
					DirectorConstants.IntervalUints[DirectorConstants.IntervalUints_Index_Code][i],
					Long.parseLong(DirectorConstants.IntervalUints[DirectorConstants.IntervalUints_Index_Offset][i]) );
			
		}
		
		ComponentUtil.setPoolName( Main.Default_DataSource_Name );
		
		try {
			//db
			DirectorCoreDao dcd = new DirectorCoreDaoImpl();
			String str_val = null;
			// 界面风格;
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.System_CloseAction_Key, DirectorConstants.System_CloseAction_Minimize); //   ComponentUtil.LookAndFeel_Current ;
			DirectorConstants.System_CloseAction_Value = str_val;
			
			// 界面风格;
			//JFrame.setDefaultLookAndFeelDecorated(false);
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.System_LookAndFeel_Key, DirectorConstants.LookAndFeel_Metal); //   ComponentUtil.LookAndFeel_Current ;
			log.debug("lookAndFeel="+str_val);
			MainFrame.lookAndFeel = str_val;
			ComponentUtil.setLookAndFeel( str_val );

			// 语言
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.System_Language_Key, DirectorConstants.System_Language_CN ); //   ComponentUtil.LookAndFeel_Current ;
			log.debug("language="+str_val);
			MainFrame.language = str_val ;
			if( str_val.equals( DirectorConstants.System_Language_CN )){
				Locale.setDefault( Locale.SIMPLIFIED_CHINESE );
				
			} else if( str_val.equals( DirectorConstants.System_Language_TW )){
				Locale.setDefault( Locale.TAIWAN );
				
			} else if( str_val.equals( DirectorConstants.System_Language_EN )){
				Locale.setDefault( Locale.ENGLISH );
				
			} else if( str_val.equals( DirectorConstants.System_Language_JP )){
				Locale.setDefault( Locale.JAPANESE );
			}
			
			//isAwokeConfirmCloseEnabled
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.Director_Reminder_AwokeCloseEnable, "1" ); //   ComponentUtil.LookAndFeel_Current ;
			DirectorContext.setAwokeCloseEnabled("1".equals(str_val)?true:false);
			

			//建立新的应用窗体，包括start,restart
			mainFrame= MainFrame.createNewInstance();   //.getInstance();
			
			//--SplashWindow splash=new SplashWindow(new JPanel()," ");
			//	  --splash.setVisible(true);
			
			//建立连接到数据库的连接池
			//	  --DBConnectionManager dbcm=DBConnectionManager.getInstance();
			//	  --Connection conn=dbcm.getConnection("oadb");
			//	  --dbcm.freeConnection("oadb",conn);
			//	  --conn=dbcm.getConnection("wfdb");
			//	  --dbcm.freeConnection("wfdb",conn);
			//定位到屏幕中央
			//frame.setSize( Frame_Size_Width ,Frame_Size_Height);	  //[800,600] [600,450]
			//ComponentUtil.setLocationToCenter(frame);
			
			//frame.initialize();
			//启动窗体消失
			//	  --splash.setVisible(false);
			//	  --splash.dispose();
			//	  --splash=null;
			
			
			//注册系统热键
			SystemHotKey.getInstance().setMainFrame(mainFrame);
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.Director_HotKey_OpenMainFrame_Key, "Ctrl+Alt+D" ); //   ComponentUtil.LookAndFeel_Current ;
			Main.MainFrame_Shortcut_Key = str_val;
			SystemHotKey.getInstance().registerHotKey(SystemHotKey.Key_OpenMainFrame, str_val);				
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.Director_HotKey_OpenMiniWindow_Key, "Alt+S" ); //   ComponentUtil.LookAndFeel_Current ;
			Main.MiniWindow_Shortcut_Key = str_val;
			SystemHotKey.getInstance().registerHotKey(SystemHotKey.Key_OpenMiniWindow, str_val);				
			//mainFrame.setSize(600, 300);
			
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.MinimizeFrame_After_OpenFileOrFolder_Key, DirectorConstants.MinimizeFrame_After_OpenFileOrFolder_Default ); //   ComponentUtil.LookAndFeel_Current ;
			DirectorConstants.MinimizeFrame_After_OpenFileOrFolder_Value = str_val;
			//frame.show();
			mainFrame.validate();
			//frame.doResize();
			//frame.doResize();
			
			//mainFrame.getLanguageManager().notifyObservers();
			mainFrame.executeChangeLanguage( Locale.getDefault() );
			mainFrame.intiSystemTray();   //放于语言改变之后
			mainFrame.getLanguageManager().addObserver( MiniDialog.getInstance() );

			//默认搜索引擎
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.System_Default_SearchEngine_Key, MainFrame.Default_Current_Panel );
			DirectorComponentUtils.setDefaultWebSearchProvider( SearchEngineFactory.getSearchEngine(str_val) );
			
			//显示应用窗体
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.System_Default_Open_Panel_Key, MainFrame.Default_Current_Panel ); //   ComponentUtil.LookAndFeel_Current ;
			mainFrame.openPanel(str_val);
			
			//启动后是否最小化
			str_val = dcd.getInitParameterFromDatabase(DirectorConstants.Director_MinedAfterStartup_Key, DirectorConstants.Director_MinedAfterStartup_Default ); //   ComponentUtil.LookAndFeel_Current ;

			mainFrame.setVisible(true); //所有初始化完成再显示
			if("1".equals(str_val)){
		        mainFrame.setExtendedState( JFrame.ICONIFIED );
			}
			
		} catch (Exception e){
			e.printStackTrace();
			JOptionPane.showMessageDialog(null,e.getMessage(),"数据库操作失败",JOptionPane.ERROR_MESSAGE);
		
		} finally {
			//wzw.util.DbUtils.closeQuietly(conn, stmt, rs);
		}
	
	}


	private static String[] startArgs;
	public static void main(String[] args) {
		startArgs = args;
		start(args);
	}
	
	/**
	 * 重新载入应用
	 */
	public static void reload(){
		//清除可见的MainFrame and Tray
		if (mainFrame!=null) {
			mainFrame.getReminderMainPanel().getTimer().removeAllTasks();
			mainFrame.hideSystemTray();
			mainFrame.setVisible(false);
			mainFrame = null;
		}
		//start a new one
		start( Main.startArgs);
	}

	/**
	 * 重启应用
	 */
	public static void restart() {
		try {
			String fileUrl = DirectorConstants.System_App_Home +"\\bin\\startup.bat";
			DirectorFileUtils.openFileQuietly(fileUrl);
			System.exit(0);  //完全退出当前的jvm
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * @param args
	 */
	public static void start(String[] args) {

		app=new Main();
		app.printStartInfo();
		app.init();
		
		//安全
		String hostName=System.getProperty("user.name")+"abcdefghijklmnopqrstuvwxyz";
		//System.out.println("user.name="+hostName);
		MD5 encrypt=new MD5();
		for (int i = 0; i < Encrypt_Time; i++) {
			hostName=encrypt.getMD5ofStr(hostName);			
		}
		Properties pro=new Properties();
		try {
			pro.load(new java.io.FileInputStream("conf/reg.key"));
		} catch (FileNotFoundException e) { 
			e.printStackTrace();
			log.info("没有注册信息文件，请与开发商联系！");
			System.exit(0);
			
		} catch (IOException e) { 
			e.printStackTrace();
			log.info("读取注册信息文件错误，请与开发商联系");
			System.exit(0);
		}
		String key=pro.getProperty("key");
		//System.out.println("hostName="+hostName + " key="+key);
		if(key==null||(!key.endsWith(hostName))){
			if ( Calendar.getInstance().get(Calendar.YEAR) > 2012 ) {	//2007年开始检查注册信息 //(new Date()).getYear()
				log.error("未授权用户，即将到期！");
				//System.exit(0);
			}
			log.info("用户授权号不正确，可免费使用！");
		}else{
			log.info("已授权的用户！");
		}			
		encrypt=null;
	}

	/**
	 * <p>可以作为Main实现app启动的接口的方法之一。</p>
	 * @author Zeven on Jun 10, 2011
	 */
	public void printStartInfo() {
		StringBuffer sbf=new StringBuffer();
		//sbf.delete(0, sbf.length());
		sbf.append( "***********************************************************\n")
			.append("*  Now start Java Server of System Director for Computer  *\n")
			.append("*  Think you for using this software.                     *\n")
			.append("*  If you have any suggestion or question                 *\n")
			.append("*       contact with zewen.wu@tom.com.                    *\n")
			.append("***********************************************************");
		//log.debug(sbf);
		System.out.println(sbf);
	}

}
